import { Record } from "./type";
const useClipboard = window.isSecureContext && 0;

/**
 * 深度获取
 * @param dataIndex  string | string[]
 * @param data  Object
 * @returns unknow
 */
export function getValueByModel(dataIndex: string| string[], data: Record): any {

  if(!data) return data;

  if (Array.isArray(dataIndex) && dataIndex.length === 1) {
    return data[dataIndex[0]];
  } else if(Array.isArray(dataIndex)){
    let key = dataIndex[0];
    return getValueByModel(dataIndex.slice(1), data[key]);
  }
  else{
      return data[dataIndex];
  }
}

/**
 * 深度设置
 * @param dataIndex string | string[]
 * @param data Object
 * @param newValue unknow
 * @returns 
 */
export function setValueByModel (dataIndex: string| string[], data: Record, newValue: unknown) {
  if(Array.isArray(dataIndex) && dataIndex.length === 1) {
    data[dataIndex[0]] = newValue;
  }
  else if(Array.isArray(dataIndex)){
    let key = dataIndex[0]
    if (data[key] === undefined) data[key] = {} // 自动填补数据层级，对深层级的 赋值 或 粘贴 场景及其重要！
    data[key] = setValueByModel(dataIndex.slice(1), data[key], newValue);
  }
  else{
    data[dataIndex] = newValue;
  }
  return data;
}

/**
 * @param {*} fn 要执行的函数
 * @param {*} interval 时间间隔
 * @param {*} options 可选参数： leading第一次是否执行, trailing 最后一次是否执行
 * @returns 
 */
export function throttle(
    fn: Function, 
    interval: number, 
    options: {
        leading: boolean,
        trailing: boolean
    } = {
        leading: true,
        trailing: true
    }
) {
    // 1.记录上一次的开始时间
    const { leading,trailing} = options
    let lastTime = 0
    let timer: any = null
   
    // 2.事件触发时, 真正执行的函数
    const _throttle = function (...args: any[]) {
      return new Promise((resolve, reject) => { //promise方式返回返回值
        // 2.1.获取当前事件触发时的时间
        const nowTime = new Date().getTime()
        if (!lastTime && !leading) lastTime = nowTime
   
        // 2.2.使用当前触发的时间和之前的时间间隔以及上一次开始的时间, 计算出还剩余多长事件需要去触发函数
        const remainTime = interval - (nowTime - lastTime)
        if (remainTime <= 0) {
          if (timer) {
            clearTimeout(timer)
            timer = null
          }
   
          // 2.3.真正触发函数
          const result = fn.apply(this, args)
          resolve(result)
          // 2.4.保留上次触发的时间
          lastTime = nowTime
          return
        }
   
        if (trailing && !timer) {
          timer = setTimeout(() => {
            const result = fn.apply(this, args)
            resolve(result)
            timer = null
            lastTime = !leading ? 0 : new Date().getTime()
          }, remainTime)
        }
      })
    }
   
    _throttle.cancel = function () {
      if (timer) clearTimeout(timer)
      timer = null
      lastTime = 0
    }
   
    return _throttle
}

/**
 * 数据深拷贝
 * @param obj 拷贝对象
 * @returns 
 */
export function deepCopy(obj: any) {
  if (obj === null || typeof obj !== 'object') {
      return obj;
  }

  if (obj instanceof Date) {
      return new Date(obj.getTime());
  }

  if (obj instanceof Array) {
      return obj.reduce((arr, item, i) => {
          arr[i] = deepCopy(item);
          return arr;
      }, []);
  }

  if (obj instanceof Object) {
      return Object.keys(obj).reduce((newObj: any, key) => {
          newObj[key] = deepCopy(obj[key]);
          return newObj;
      }, {});
  }
}

export function getCopyPasteTextarea(): HTMLTextAreaElement {
  const id = 'copy-paste-textarea'
  let textarea = document.querySelector('#' + id) as HTMLTextAreaElement | null;
  if (!textarea) {
    // 创建输入框
    textarea = document.createElement('textarea');
    textarea.id  = id;
    textarea.style.position = 'fixed'
    textarea.style.width = '1px'
    textarea.style.height = '1px'
    textarea.style.opacity = '0'
    textarea.style.zIndex = '-1'
    textarea.style.transform = 'translate3d(500vw, 500vh, 0)'
    document.body.appendChild(textarea);
  }
  return textarea;
}

export function awaitTime(time: number) {
  return new Promise((reslove) => {
    setTimeout(() => reslove(true), time)
  })
}

/**
 * 剪切板写入
 * @param text
 * @returns
 */
export async function writeTextToClipboard (text: string) {
  // console.group("粘贴板写入数据")
  try{
    useClipboard ? await navigator.clipboard.writeText(text) : await Promise.reject();
    // console.info("粘贴板写入成功")
  } catch(e) {
    // 创建输入框
    const textarea = getCopyPasteTextarea();
    textarea.value = text
    textarea.select()

    await awaitTime(0)

    // 复制命令
    const result = document.execCommand('copy', true)
    // console.info("execCommand copy 执行: ", result)
  } finally {
    // console.groupEnd()
  }
}

/**
 * 读取剪切板
 * @returns 
 */
export async function readTextToClipboard(){
  // console.group("粘贴板读取数据")
  const currentActiveElement: Element | null = document.activeElement

  try {
    const clipText = useClipboard ? await navigator.clipboard.readText() : await Promise.reject();
    // console.info('clipboard', clipText)
    return clipText;
  } catch(e) {
    
    // 创建输入框
    const textarea = getCopyPasteTextarea();
    textarea?.select()

    await awaitTime(0)

    // 粘贴命令
    // const result = document.execCommand('paste', false)
    const text: string = textarea.value;
    // console.info('execCommand paste 执行: ', result, text)
    
    const warpSplit = "\r";
    const enterSplit = "\n";
    return text.replace(new RegExp(enterSplit, 'g'), warpSplit)
  } finally {
    // console.groupEnd()
    currentActiveElement?.select?.();
  }
}


/**
 * 验证小位数
 * @param value 验证值
 * @param options { maxDecimal 最大位数, minDecimal 最小位数, message 错误提示 }
 */
export const validatorDecimal = function (
  value: string | number,
  options: {
    maxDecimal: number;
    minDecimal?: number;
    message: string | ((value: string | number) => string);
  },
): Promise<string | void> {
  const { maxDecimal, minDecimal, message } = options;
  const getMessage = (): string => {
    if (typeof message === 'string') return message;
    return message(value);
  };
  let decimal: number = 0;

  const splitValue: string[] = String(value).split('.');
  if (splitValue.length > 1) {
    decimal = splitValue.at(-1)?.length ?? 0;
  }

  if (maxDecimal !== undefined && decimal > maxDecimal)
    return Promise.reject(getMessage());

  if (minDecimal !== undefined && decimal < minDecimal)
    return Promise.reject(getMessage());

  return Promise.resolve();
};

/**
 * 判断是否需要显示提示
 * @param textElement 装载文本容器
 * @param parentElement 防止溢出装载文本容器的父容器
 * @returns 
 */
export const computedOpenTooltipVisible = (textElement?: HTMLElement, parentElement?: HTMLElement, offset: number = 0) => {
  if(!textElement || !parentElement) return true;

  const info = textElement?.getBoundingClientRect()
  const pinfo =parentElement?.getBoundingClientRect()
  return info.width - pinfo.width > offset
}